#include "sys/socket.h"
#include "netinet/in.h"
#include "errno.h"
#include "stdio.h"

#include "udp_funs.h"

#define BUFSIZE 50

void udp_client()
{
	int sock;
	struct sockaddr_in client_addr, remote_send_addr, remote_recv_addr;
	int bind_ret_val, send_ret_val, recv_ret_val;
	char buf[BUFSIZE];
	int sockaddr_len;
	int one = 1;
	int bind_port;

	memset(&client_addr, 0, sizeof(client_addr));
	memset(&remote_send_addr, 0, sizeof(remote_send_addr));
	memset(&remote_recv_addr, 0, sizeof(remote_recv_addr));
	sockaddr_len = sizeof(struct sockaddr);

	sock = socket(PF_INET, SOCK_DGRAM, 0);
	if(-1 == sock) {
		printf("&udp_client: fail to create socket, program exit.\n");
		printf("udp_client: the failure reason is %d.\n", errno);
		exit(0);
	}

	printf("plz enter the port to bind the udp client:\n");
	scanf("%d", &bind_port);
	client_addr.sin_family = AF_INET;
	client_addr.sin_port = htons(bind_port);
	client_addr.sin_addr.s_addr = INADDR_ANY;

	if(-1 == setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
			&one, sizeof(one))) {
		printf("&udp_client: fail to setsockopt, program exit.\n");
		printf("&udp_client: the failure reason is %d.\n", errno);
		exit(0);
	}

	bind_ret_val = bind(sock, (struct sockaddr*)&client_addr, sizeof(struct sockaddr));
	if(-1 == bind_ret_val) {
		printf("&udp_client: fail to bind, program exit.\n");
		printf("udp_client: the failure reason is %d.\n", errno);
		exit(0);
	}

	remote_send_addr.sin_family = AF_INET;
	remote_send_addr.sin_port = htons(8000);
	remote_send_addr.sin_addr.s_addr = inet_addr("127.0.0.1");

	while(1) {
		printf("plz enter a string to send to server:\n");
		if(NULL != fgets(buf, BUFSIZE, stdin)) {
#ifdef DEBUG_UDP
			printf("The length of input string is %d\n", strlen(buf));
#endif
			if(0 == strcmp(buf, "quit\n")) {
				break;
			}

			send_ret_val = sendto(sock, buf, strlen(buf), 0,
					(struct sockaddr*)&remote_send_addr, sizeof(struct sockaddr));
#ifdef DEBUG
			printf("The length of sent message is %d\n", send_ret_val);
#endif
			if(-1 == send_ret_val) {
				printf("&udp_client: fail to send message to remote, program exit\n");
				printf("udp_client: the failure reason is %d.\n", errno);
				exit(0);
			}

			memset(buf, 0, BUFSIZE);
			recv_ret_val = recvfrom(sock, buf, BUFSIZE, 0,
					(struct sockaddr*)&remote_recv_addr, &sockaddr_len);
			if(-1 == recv_ret_val) {
				printf("&udp_client: fail to recevie messages from remote, program exit.\n");
				printf("udp_client: the failure reason is %d.\n", errno);
				exit(0);
			}
			buf[recv_ret_val] = '\0';
			printf("&udp_client: the remote address is %s\n", inet_ntoa(remote_recv_addr.sin_addr));
			printf("&udp_client: the remote port is %d\n", ntohs(remote_recv_addr.sin_port));
			printf("&udp_clinet: the message received from remote is %s\n", buf);
		}

	}

	close(sock);

	return;
}
